﻿using System;
using System.Text;
using System.Collections.Specialized;
using System.Net;
using System.IO;

namespace OAuthTools
{
    public class OAuthRequest
    {
        private readonly HttpWebRequest _request;
        private static byte[] _content;

        public string GetResponse(NameValueCollection queryParameters = null)
        {
            try
            {
                /*POST method*/
                if (queryParameters != null)
                {
                    var sb = new StringBuilder();
                    for (var i = 0; i < queryParameters.AllKeys.Length; i++)
                    {
                        var key = queryParameters.AllKeys[i];

                        sb.AppendFormat("{0}={1}", Uri.EscapeDataString(key), Uri.EscapeDataString(queryParameters[key]));

                        if (i < queryParameters.Count - 1)
                            sb.Append("&");

                    }

                    _content = Encoding.ASCII.GetBytes(sb.ToString());
                    _request.ContentLength = _content.Length;

                    using (var stream = _request.GetRequestStream())
                    {
                        if (_request.ContentLength > 0)
                            stream.Write(_content, 0, _content.Length);
                    }

                }

                using (var response = _request.GetResponse())
                {
                    var stream = response.GetResponseStream();
                    using (var reader = new StreamReader(stream))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
            catch (WebException ex)
            {
                //If something is wrong, We'll retrieve the server response.
                /*    HTTP 400 Bad Request
                        o Unsupported parameter
                        o Unsupported signature method
                        o Missing required parameter
                        o Duplicated OAuth Protocol Parameter
                      HTTP 401 Unauthorized
                        o Invalid Consumer Key
                        o Invalid / expired Token
                        o Invalid signature
                        o Invalid / used nonce
                */
                if (ex.Response is HttpWebResponse)
                {
                    using (var reader = new StreamReader(ex.Response.GetResponseStream()))
                    {
                        var result = reader.ReadToEnd();
                        return result;
                    }
                }

                throw;
            }
        }

        //  2. For each parameter, the name is immediately followed by an ‘=’ character (ASCII code 61), a ‘”’ character (ASCII code 34), the parameter value (MAY be empty), and another ‘”’ character (ASCII code 34).
        //  3. Parameters are separated by a comma character (ASCII code 44) and OPTIONAL linear whitespace.
        //  4. The OPTIONAL realm parameter is added 
        /// <summary>
        /// The OAuth Protocol Parameters are sent in the Authorization  header the following way:
        /// 1.  Parameter names and values are encoded.
        /// </summary>
        /// <param name="parameters">oAuthParameters</param>
        /// <param name="url"></param>
        /// <param name="method">Http Method</param>
        /// <param name="proxy"></param>
        public OAuthRequest(NameValueCollection parameters, string url, string method, IWebProxy proxy = null)
        {
            ServicePointManager.Expect100Continue = false;
            ServicePointManager.UseNagleAlgorithm = false;

            var header = new StringBuilder();

            header.Append("OAuth ");

            for (var i = 0; i < parameters.Count; i++)
            {
                var key = parameters.GetKey(i);
                header.Append(string.Format("{0}=\"{1}\"", key, parameters[key]));

                if (i < parameters.Count - 1)
                    header.Append(",");
            }

            _request = CreateHttpWebRequest(url, method, proxy);

            _request.Headers["Authorization"] = header.ToString();

        }

        private static HttpWebRequest CreateHttpWebRequest(string url, string method, IWebProxy proxy = null)
        {
            var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
            httpWebRequest.Method = method.ToUpper();

            if (proxy != null) httpWebRequest.Proxy = proxy;

            if (method == HttpMethod.Post)
                httpWebRequest.ContentType = "application/x-www-form-urlencoded";

            return httpWebRequest;
        }
    }
}
